﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.IO;

namespace LED_Tester
{
    public class ClassSpectralMeter
    {
        private ColorLib.ColorMeasure colorLib = new ColorLib.ColorMeasure();

        public struct Param
        {
            public bool IsAutoAdjust;
            public int IntTime;
            public int STA;
            public int BCW;
        }

        public struct Result
        {
            public double uWatt;
            public double lm;
            public double x;
            public double y;
            public double z;
            public double u;
            public double v1960;
            public double v1976;
            public double pwl;
            public double cwl;
            public double dwl;
            public double purity;
            public double halfWidth;
            public double colorTemp;
            public double ra;
            public double[] r;
            public double maxEnergy;

            public double[] waveleng;
            public double[] signSpec;
            public double[] calcSpec;

            public double lux;
            public double candela;
            public double peakLeft;
            public double peakRight;
            public double heightLeft;
            public double heightRight;
        }

        public int Join()
        {
            int ret = -1;

            colorLib.LoadDefault();

            colorLib.DoConnect(0);

            if (!colorLib.Connected)
            {
                ret = 1;
            }
            else
            {
                colorLib.Nonlinearity = true;
                colorLib.IntSphere = true;

                colorLib.CalibrationFile = Application.StartupPath + "\\Default.CAL";
                colorLib.SaveDefault();
                colorLib.LoadDefault();

                ret = 0;
            }
            return ret;
        }

        public void Exit()
        {
            if (colorLib.Connected)
            {
                colorLib.DoDisconnect();
            }
        }

        public void AutoAdjust(ref int intTime)
        {
            if (colorLib.Connected)
            {
                double[] signSpec = new double[2048];
                Array signSpecArray = signSpec;
                double stanMax = 75 * 65535 / 100;
                double stanMin = 65 * 65535 / 100;
                double signMax = 0;

                colorLib.IntTime = intTime * 1000;
                colorLib.SaveDefault();
                colorLib.LoadDefault();
                colorLib.DoScan(0);
                colorLib.GetSpectrum(ref signSpecArray);

                signSpecArray.CopyTo(signSpec, 0);
                signMax = signSpec.Max();
                if ((stanMin <= signMax) && (signMax <= stanMax))
                {
                    colorLib.IntTime = intTime * 1000;
                    colorLib.SaveDefault();
                    colorLib.LoadDefault();
                }
                else
                {
                    intTime = 1;
                    colorLib.IntTime = intTime * 1000;
                    colorLib.SaveDefault();
                    colorLib.LoadDefault();
                    colorLib.DoScan(0);
                    colorLib.GetSpectrum(ref signSpecArray);

                    signSpecArray.CopyTo(signSpec, 0);
                    signMax = signSpec.Max();

                    if (signMax > (90 * 65535 / 100))
                    {
                        intTime = 1;
                        colorLib.IntTime = intTime * 1000;
                        colorLib.SaveDefault();
                        colorLib.LoadDefault();
                    }
                    else
                    {
                        intTime = (int)(65535 / signMax);
                        if (intTime > 3000)
                        {
                            intTime = 3000;
                            colorLib.IntTime = intTime * 1000;
                            colorLib.SaveDefault();
                            colorLib.LoadDefault();
                        }
                        else
                        {
                            colorLib.IntTime = intTime * 1000;
                            colorLib.SaveDefault();
                            colorLib.LoadDefault();
                        }
                    }
                }
            }
        }

        public void Set(Param param)
        {
            if (colorLib.Connected)
            {
                colorLib.IntTime = param.IntTime;
                colorLib.STA = param.STA;
                colorLib.BCW = param.BCW;
                colorLib.SaveDefault();
                colorLib.LoadDefault();
            }
        }

        public void Measure(Param param, ref Result result)
        {
            if (colorLib.Connected)
            {
                result.r = new double[15];
                result.waveleng = new double[2048];
                result.signSpec = new double[2048];
                result.calcSpec = new double[2048];

                Array rArray = result.r;
                Array wavelengArray = result.waveleng;
                Array signSpecArray = result.signSpec;
                Array calcSpecArray = result.calcSpec;

                if (param.IsAutoAdjust)
                {
                    AutoAdjust(ref param.IntTime);
                }
                else
                {
                    colorLib.IntTime = param.IntTime * 1000;
                }

                colorLib.STA = param.STA;
                colorLib.BCW = param.BCW;
                colorLib.SaveDefault();
                colorLib.LoadDefault();
                colorLib.DoScan(0);

                colorLib.GetuWatt(380d, 780d, ref result.uWatt);
                colorLib.GetLumen(1d, ref result.lm, ref result.lux, ref result.candela);
                colorLib.GetSmallxyz(ref result.x, ref result.y, ref result.z);
                colorLib.Getuv(ref result.u, ref result.v1960);
                colorLib.GetDWL(ref result.dwl, ref result.purity, ref result.cwl);
                colorLib.FindPeak(2, ref result.peakLeft, ref result.heightLeft, ref result.peakRight, ref result.heightRight, ref result.halfWidth);
                colorLib.GetColorTemp(ref result.colorTemp);
                colorLib.GetRa(ref result.ra, ref rArray);
                colorLib.GetWaveLen(ref wavelengArray);
                colorLib.GetSpectrum(ref signSpecArray);
                colorLib.GetEnergySpectrum(ref calcSpecArray);

                rArray.CopyTo(result.r, 0);
                wavelengArray.CopyTo(result.waveleng, 0);
                signSpecArray.CopyTo(result.signSpec, 0);
                calcSpecArray.CopyTo(result.calcSpec, 0);

                result.v1976 = result.v1960 / 3 * 2;

                int left = 0, right = 0;
                left = Array.IndexOf(result.waveleng, result.peakLeft);
                right = Array.IndexOf(result.waveleng, result.peakRight);

                if (left == -1 || right == -1)
                {
                    if (left == -1 && right != -1)
                    {
                        result.pwl = result.peakRight;
                    }
                    else if (left != -1 && right == -1)
                    {
                        result.pwl = result.peakLeft;
                    }
                    else
                    {
                        result.pwl = 0;
                    }
                }
                else
                {
                    if (result.calcSpec[left] >= result.calcSpec[right])
                    {
                        result.pwl = result.peakLeft;
                    }
                    else
                    {
                        result.pwl = result.peakRight;
                    }
                }
                result.candela *= 1000;
                result.maxEnergy = result.signSpec.Max() / 65535;
            }
        }

        public void MeasureCandela(Param param, ref double candela)
        {
            if (colorLib.Connected)
            {
                double lm = 0.0d;
                double lux = 0.0d;

                if (param.IsAutoAdjust)
                {
                    AutoAdjust(ref param.IntTime);
                }
                else
                {
                    colorLib.IntTime = param.IntTime * 1000;
                }

                colorLib.STA = param.STA;
                colorLib.BCW = param.BCW;
                colorLib.SaveDefault();
                colorLib.LoadDefault();
                colorLib.DoScan(0);
                colorLib.GetLumen(1.0d, ref lm, ref lux, ref candela);
                candela *= 1000;
            }
        }

        public void Dark()
        {
            if (colorLib.Connected)
            {
                colorLib.SetDarkEx();
            }
        }

        public void Standard()
        {
            if (colorLib.Connected)
            {
                colorLib.SetRefEx();
            }
        }

        public void Calibration(string lampFileName, string stanFileName)
        {
            if (colorLib.Connected)
            {
                colorLib.BuildCalFile(lampFileName, "", "", "", "", stanFileName);
                colorLib.CalibrationFile = stanFileName;
            }
        }
    }
}
